<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>Embedding state-machine-cat scripts in html</title>
    <meta
      http-equiv="content-security-policy"
      content="
        connect-src 'self';
        font-src 'none';
        frame-src 'none';
        img-src 'self' data:;
        manifest-src 'self';
        media-src 'none';
        object-src 'none';
        script-src 'self' 'unsafe-eval';
        style-src 'unsafe-inline';
        trusted-types 'none';
        form-action 'none'"
    />
    <script
      src="state-machine-cat-inpage.min.js"
      type="module"
      defer
      integrity="sha512-pjQTur4XNDsB33+lAJhzXhUMHCKiyzz5IVEYloAZbsoNNjEp1wr0VNQBs9E5x5GufJ0UWNtS/P9zDBuBgbbFVQ=="
    ></script>
    <style
    >
      body { font-family: sans-serif; margin: 0 auto; max-width: 799px;
      line-height: 1.6; font-size: 18px; padding-bottom: 3em; background-color:
      #fff; } th{ text-align: left; background-color: #eee}
      tr:nth-child(even) { background-color: #f3f3f3} pre {
      background-color:#eee; font-size:smaller} h1, h2, h3 { line-height: 1.2}
      table,tr,th,td {font-size: inherit} table {padding-top:1em}
    </style>
  </head>

  <body>
    <main>
      <h1>Embedding state-machine-cat scripts in html</h1>
      <p>
        In your
        <code>head</code>:
      </p>

      <pre
      >&lt;script
      src="https://state-machine-cat.js.org/state-machine-cat-inpage.min.js"
      type="module" defer> &lt;/script></pre>

      <p>In your <code>body</code>:</p>
      <pre
      >&lt;script type="text/x-smcat">
    on [color="darkgreen" active], off [color="maroon"]; 
    on => off [color="red"]: flickSwitch() / makeNoise("off.wav"); 
    off => on [color="#009900"]: flickSwitch() / makeNoise("on.wav"); 
&lt;/script></pre>
      <p>result:</p>
      <center>
        <script type="text/x-smcat">
          on [color="darkgreen" active], off [color="maroon"]; on => off
          [color="red"]: flickSwitch() / makeNoise("off.wav"); off => on
          [color="#009900"]: flickSwitch() / makeNoise("on.wav");
        </script>
      </center>

      <h2>Introduction</h2>
      <p>
        When you include the state-machine-cat 'inpage' script in the head of
        your page like so ...
      </p>
      <pre
      >&lt;script
      src="https://state-machine-cat.js.org/state-machine-cat-inpage.min.js"
      type="module" defer> &lt;/script></pre>
      <p>
        ... it will extend html with three script types, which will render into
        state machine diagrams:
        <table>
          <thead><tr><th>type</th><th>what's it do?</th></tr></thead>
          <tbody>
            <tr>
              <td>
                <code>text/x-smcat</code>
              </td>
              <td>accepts <code>smcat</code></td>
            </tr>
            <tr>
              <td>
                <code>text/x-scxml</code>
              </td>
              <td>accepts <code>SCXML</code></td>
            </tr>
            <tr>
              <td>
                <code>text/x-smcat-json</code>
              </td>
              <td>accepts smcat's abstract syntax tree format</td>
            </tr>
          </tbody>
        </table>
      </p>

      <p>
        When that is done, you can use
        <code>script</code>s with one of the types above in the body of your
        page (e.g.
        <code>&lt;script type="text/x-smcat">a=>b;&lt;/script></code>).
      </p>
      <p>
        These scripts take optional
        <code>data</code>
        attributes you can use to influence how things get rendered:
        <table>
          <thead>
            <tr>
              <th>attribute</th>
              <th>description</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td>
                <code>data-direction</code>
              </td>
              <td>
                Direction the graph should be rendered in. Possible values:
                <code>top-down</code>
                (default),
                <code>left-right</code>,
                <code>bottom-top</code>,
                <code>right-left</code>.
              </td>
            </tr>
            <tr>
              <td>
                <code>data-output-type</code>
              </td>
              <td>
                What you want to have rendered. Defaults to
                <code>svg</code>
                (for diagrams), but it's also possible to re-render the state
                machine in one of the avaible description languages:
                <code>smcat</code>,
                <code>scxml</code>
                and
                <code>json</code>.
              </td>
            </tr>
            <tr>
              <td>
                <code>data-engine</code>
              </td>
              <td>
                state-machine-cat currently uses
                <a href="https://graphviz.org">GraphViz</a>
                as a render engine. With the `data-engine` attribute it's
                possible to influence which layout algorithm GraphViz uses. By
                default it's
                <code>dot</code>, but it's also possible to specify other values
                are e.g.
                <code>fdp</code>
                or
                <code>osage</code>.
              </td>
            </tr>
            <tr>
              <td>data-desugar</td>
              <td>Boolean attribute that, when included, will make the render
                engine
                <a
                  href="https://github.com/sverweij/state-machine-cat/blob/main/docs/desugar.md"
                >desugar</a>
                the diagram.
              </td>
            </tr>
          </tbody>
        </table>
      </p>

      <h2>Examples</h2>

      <h3>Read from an url</h3>
      <p>Pass the url in the <code>src</code> attribute of the script tag:</p>
      <pre>&lt;script type="text/x-smcat"
      <mark
        >src="samples/cat.smcat"</mark>>&lt;/script></pre>
      <center>
        <script type="text/x-smcat" src="samples/cat.smcat"></script>
      </center>

      <h2>Orientation with <code>data-direction</code></h2>
      <p>
        In this example the states get layed out from left to right instead of
        top down because the script includes the
        <code>data-direction</code>
        attribute:
      </p>
      <pre
      >&lt;script type="text/x-smcat" src="samples/cassetteplayer.smcat"
      <mark
        >data-direction="left-right"</mark>> &lt;/script></pre>
      <center>
        <script
          type="text/x-smcat"
          src="samples/cassetteplayer.smcat"
          data-direction="left-right"
        ></script>
      </center>

      <h2>De-sugaring a state machine</h2>
      <p>
        If you want to render a state machine without any pseudo states that
        only exist for 'syntactic sugar', you can do this with the
        `data-desugar` attribute.
      </p>
      <h3>as is</h3>
      <pre
      >&ltscript src="samples/desugarable.smcat" type="text/x-smcat"
      data-direction="left-right" &lt/script></pre>

      <script
        src="samples/desugarable.smcat"
        type="text/x-smcat"
        data-direction="left-right"
      ></script>

      <h3>de-sugared</h3>
      <pre
      >&ltscript src="samples/desugarable.smcat" type="text/x-smcat"
      data-direction="left-right"
      <mark
        >data-desugar=true</mark>> &lt/script></pre>
      <p>
        You'll notice the
        <em>choice</em>
        is replaced by two regular transitions and the
        <em>junction</em>
        on the right with all permutations of transitions it describes:
      </p>
      <script
        src="samples/desugarable.smcat"
        type="text/x-smcat"
        data-desugar="true"
        data-direction="left-right"
      ></script>

      <h2>Using SCXML</h2>
      <p>
        It's possible to embed SCXML:
      </p>
      <pre>&lt;script <mark
        >type="text/x-scxml"</mark>> 
    &lt;scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0"> 
      &lt;state id="off">
        &lt;onentry>&lt;log expr="winston.log('switched lamp on')"/>&lt;/onentry>
        &lt;transition event="switch_flipped" target="on"/> 
      &lt;/state> 
      &lt;state id="on"> 
        &lt;transition event="switch_flipped" target="off"/> 
      &lt;/state>
    &lt;/scxml> 
&lt;/script></pre>
      <center>
        <script type="text/x-scxml">
          <scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0"> <state
          id="off"> <onentry><log expr="winston.log('switched lamp
          on')"/></onentry> <transition event="switch_flipped" target="on"/>
          </state> <state id="on"> <transition event="switch_flipped"
          target="off"/> </state> </scxml>
        </script>
      </center>

      <p>
        or likewise, using a
        <code>src</code>
        attribute to load SCXML from somewhere else:
      </p>
      <pre>&ltscript <mark>type="text/x-scxml" src="samples/sprint-states.scxml"</mark>>&lt/script></pre>
      <center>
        <script
          type="text/x-scxml"
          src="samples/sprint-states.scxml"
        ></script>
      </center>

      <h2>Output formats other than <code>svg</code></h2>
      <p>
        If you, for some reason don't want to render an svg, but one of the
        textual formats, you can specify an output type. This example specifies
        <code>json</code>
        to show the abstract syntax tree (AST):
      </p>
      <pre
      >&lt;script type="text/x-smcat" data-output-type="json">
    off: entry/ &lt;log expr="winston.log('switched lamp on')"/>,
    on; 
    
    off => on:
    switch_flipped; on => off: switch_flipped; 
&lt;/script></pre>

      <p>which will render this AST:</p>
      <script type="text/x-smcat" data-output-type="json">
        off: entry/ <log expr="winston.log('switched lamp on')"/>, on; off =>
        on: switch_flipped; on => off: switch_flipped;</script>

      <h2>Error handling</h2>
      <p>
        When the render engine detects an error it will show the error. E.g.
        trying to render an invalid script, like so...
      </p>
      <pre>&lt;script type="text/x-smcat">a => nosemicolon&lt;/script></pre>

      <p>
        ... will yield this:
      </p>

      <script type="text/x-smcat">a => nosemicolon</script>

      <p>
        ... or when it couldn't find the script at the other end of the URL ...
      </p>

      <pre>&lt;script src="this_thing_doesnot_exist" type="text/x-smcat"/></pre>

      <script src="this_thing_doesnot_exist" type="text/x-smcat"></script>
    </main>
  </body>
</html>